﻿// --- Copyright (c) 2010 Steven Hartgers ---
// Copyright (C) 2010 Steven Hartgers All rights are reserved.
// Author contact: fiinix00/at\gmail.com
// ------------------------------------------------------------------------
// This program is free software: you can redistribute it and/or modify 
// it under the terms of the GNU General Public License as published by 
// the Free Software Foundation, either version 3 of the License, or 
// (at your option) any later version. 
//  
// This program is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
// GNU General Public License for more detail
//  
// You should have received a copy of the GNU General Public License 
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
// ------------------------------------------------------------------------
// COPYRIGHT NOTICE: This copyright notice may NOT be removed, obscured or modified 
// without written consent from the author.
// --- End copyright notice --- 


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
using Hack.Extensions;
namespace Hack.Software
{
    public static class Windows
    {
        public static bool IsX64
        {
            get
            {
                switch (IntPtr.Size * 8)
                {
                    case (int)Architecture.x64:
                        return true;
                    default: 
                        return false;
                }
            }
        }
        public static bool Isx86
        {
            get
            {
                switch (IntPtr.Size * 8)
                {
                    case (int)Architecture.x64: return false;
                    default: return true;
                }
            }
        }

        public enum Architecture : int { x86 = 32, x64 = 64 }
        public enum VersionsWin32Windows : int { Windows95 = 0, Windows98 = 10, WindowsME = 90 }
        public enum VersionWin32NT : int { NT_3_51 = 3, NT_4_0 = 4, Windows_2000_XP = 5, Windows_Vista_7 = 6 }
        public enum Version : int { Windows95, Windows98, Windows98SE, WindowsME, NT3_51, NT4_0, Windows2000, WindowsXP, WindowsVista, Windows7, UnknownWin32Windows, UnknownWin32NT, TotalyUnknown }


        public class OSVersion
        {
            public Architecture Architecture { get; internal set; }
            public Version Version { get; internal set; }
            public string ServicePack { get; internal set; }
            public OSVersion(Architecture architecture, Version version, string ServicePack)
            {
                this.Architecture = architecture;
                this.Version = version;
                this.ServicePack = ServicePack;
            }

            public override string ToString()
            {
                string operatingSystem = String.Empty;

                //Got something.  Let's prepend "Windows" and get more info.
                operatingSystem = this.Version.AsString();
                //See if there's a service pack installed.
                if (this.ServicePack != "")
                {
                    //Append it to the OS name.  i.e. "Windows XP Service Pack 3"
                    operatingSystem += " " + this.ServicePack;
                }
                //Append the OS architecture.  i.e. "Windows XP Service Pack 3 32-bit"
                operatingSystem += " " + this.Architecture.AsString() + "-bit";
                return operatingSystem;
            }
        }

        public static string AsString(this OSVersion os)
        {
            return os.ToString();
        }
        public static string AsString(this Version version)
        {
            return Enum.GetName(typeof(Version), version).Replace('_', '.');
        }
        public static string AsString(this Architecture arch)
        {
            return Enum.GetName(typeof(Architecture), arch).Replace('_', '.');
        }


        public static Architecture GetOSArchitecture()
        {
            string pa = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE");
            return ((String.IsNullOrEmpty(pa) || String.Compare(pa, 0, "x86", 0, 3, true) == 0) ? (Architecture)32 : (Architecture)64);
        }
        public static Version GetOSVersion()
        {
            OperatingSystem os = Environment.OSVersion;
            //Get version information about the os.
            System.Version vs = os.Version;


            if (os.Platform == PlatformID.Win32Windows)
            {
                //This is a pre-NT version of Windows
                switch (vs.Minor)
                {
                    case 0:
                        return Version.Windows95;
                    //operatingSystem = "95";
                    case 10:
                        if (vs.Revision.ToString() == "2222A")
                            return Version.Windows98SE;
                        //operatingSystem = "98SE";
                        else
                            return Version.Windows98;
                    //operatingSystem = "98";

                    case 90:
                        return Version.WindowsME;
                    //operatingSystem = "Me";

                    default:
                        return Version.UnknownWin32Windows;
                }
            }
            else if (os.Platform == PlatformID.Win32NT)
            {
                switch (vs.Major)
                {
                    case 3:
                        return Version.NT3_51;
                    //operatingSystem = "NT 3.51";

                    case 4:
                        return Version.NT4_0;
                    //operatingSystem = "NT 4.0";

                    case 5:
                        if (vs.Minor == 0)
                            return Version.Windows2000;
                        //operatingSystem = "2000";
                        else
                            return Version.WindowsXP;
                    //operatingSystem = "XP";

                    case 6:
                        if (vs.Minor == 0)
                            return Version.WindowsVista;
                        //operatingSystem = "Vista";
                        else
                            return Version.Windows7;
                    //operatingSystem = "7";

                    default:
                        return Version.UnknownWin32NT;
                }
            }
            return Version.TotalyUnknown;
        }
        public static string GetOSServicePack()
        {
            return Environment.OSVersion.ServicePack;
        }
        internal static string GetOSInfo()
        {

            //Get Operating system information.
            OperatingSystem os = Environment.OSVersion;
            ////Get version information about the os.
            //Version vs = os.Version;

            ////Variable to hold our return value
            string operatingSystem = GetOSVersion().AsString();


            //if (os.Platform == PlatformID.Win32Windows)
            //{
            //    //This is a pre-NT version of Windows
            //    switch (vs.Minor)
            //    {
            //        case 0:
            //            operatingSystem = "95";
            //            break;
            //        case 10:
            //            if (vs.Revision.ToString() == "2222A")
            //                operatingSystem = "98SE";
            //            else
            //                operatingSystem = "98";
            //            break;
            //        case 90:
            //            operatingSystem = "Me";
            //            break;
            //        default:
            //            break;
            //    }
            //}
            //else if (os.Platform == PlatformID.Win32NT)
            //{
            //    switch (vs.Major)
            //    {
            //        case 3:
            //            operatingSystem = "NT 3.51";
            //            break;
            //        case 4:
            //            operatingSystem = "NT 4.0";
            //            break;
            //        case 5:
            //            if (vs.Minor == 0)
            //                operatingSystem = "2000";
            //            else
            //                operatingSystem = "XP";
            //            break;
            //        case 6:
            //            if (vs.Minor == 0)
            //                operatingSystem = "Vista";
            //            else
            //                operatingSystem = "7";
            //            break;
            //        default:
            //            break;
            //    }
            //}
            //Make sure we actually got something in our OS check
            //We don't want to just return " Service Pack 2" or " 32-bit"
            //That information is useless without the OS version.
            if (operatingSystem != "")
            {
                //Got something.  Let's prepend "Windows" and get more info.
                operatingSystem = "Windows " + operatingSystem;
                //See if there's a service pack installed.
                if (os.ServicePack != "")
                {
                    //Append it to the OS name.  i.e. "Windows XP Service Pack 3"
                    operatingSystem += " " + os.ServicePack;
                }
                //Append the OS architecture.  i.e. "Windows XP Service Pack 3 32-bit"
                operatingSystem += " " + Convert.ToString(GetOSArchitecture()) + "-bit";
            }
            //Return the information we've gathered.
            return operatingSystem;
        }

        public static OSVersion GetFullOSInfo()
        {
            return new OSVersion(GetOSArchitecture(), GetOSVersion(), GetOSServicePack());
        }
    }
    public static class NetFramework
    {
        public static DateTime CompilationTime(this Version v)
        {
            return new DateTime(v.Build * TimeSpan.TicksPerDay + v.Revision * TimeSpan.TicksPerSecond * 2).AddYears(1999).AddDays(-1);
        }

        public class NetFrameworkVersion
        {
            public string GlobalVersion { get; internal set; }
            public string FullVersion { get; internal set; }
            public int? ServicePack { get; internal set; }

            public override string ToString()
            {
                return GlobalVersion + (ServicePack != null ? " SP" + ServicePack : "");
            }
        }

        public static List<NetFrameworkVersion> FrameworkVersions()
        {
            RegistryKey componentsKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Net Framework Setup\NDP\");
            return componentsKey.SubKeys((n, k) =>
                new NetFrameworkVersion
                {
                    GlobalVersion = n,
                    FullVersion = (string)k.GetValue("Version"),
                    ServicePack = (int?)k.GetValue("SP")
                }).ToList();
        }


        internal static RegistryKey GetPolicy()
        {
            return Registry.LocalMachine.OpenSubKey("SOFTWARE").OpenSubKey("Microsoft").OpenSubKey(".NETFramework").OpenSubKey("Policy");
        }

        public static bool v1_0_Installed
        {
            get
            {
                try
                {
                    return GetPolicy().OpenSubKey("v1.0").GetValue("3705").ToString() == "3321-3705";
                }
                catch (Exception)
                {
                    return false;
                }
            }
        }
        public static bool v1_1_Installed
        {
            get
            {
                try
                {
                    return GetPolicy().OpenSubKey("v1.1").GetValue("4322").ToString() == "3706-4322";
                }
                catch (Exception)
                {
                    return false;
                }
            }
        }
        public static bool v2_0_Installed
        {
            get
            {
                try
                {
                    return GetPolicy().OpenSubKey("v2.0").GetValue("50727").ToString() == "50727-50727";
                }
                catch (Exception)
                {
                    return false;
                }
            }
        }
    }
}
